
// Include the event emitter class - the controller is a specialized
// instance of the event emitter and will emit the events:
//
// - data / response
// - error / errorType (HTTP Status code)
var sys = require('sys');
var querystring = require('querystring');

var EventEmitter = require( "events" ).EventEmitter;

//var registerService = require( "./services/registerService.js" );


// ---------------------------------------------------------- //
// ---------------------------------------------------------- //


// Create an instance of our event emitter.
var controller = new EventEmitter();


// Add a handle method to the event emitter instance (controller)
// so that the HTTP server will be able to pass the request off for
// proper routing.
controller.handle = function( request, response ){

    // We are going to be looking at urls for RESTful commands.
    // These will be in the form of:
    //
    // NOTE: I am using the term RESTful in the loosest sense.
    // Really, this is just easy for illustration purposes.
    //
    // users/get
    // users/{id}/get
    // users/{id}/delete
    // users/add/{name}


    // Define our patterns.
    var patterns = {
        getAll: new RegExp( "user/get", "i" ),
        get: new RegExp( "user/(\\d+)/get", "i" ),
        delete: new RegExp( "user/(\\d+)/delete", "i" ),
        add: new RegExp( "user/add/([^/]+)", "i" )
    };

    var me = this;

    // Strip off the leading and trailing slashes.
    var restUri = request.url.replace(
        new RegExp( "^/|/$", "g" ),
        ""
    );

    sys.puts(restUri);
    // Loop over the patterns to see if any match.
    for (var patternKey in patterns){
        // Try to match the pattern against the URL.
        if ( match = restUri.match( patterns[ patternKey ] ) ){
            // Pass the request off to the service layer. Since
            // the service layer is performing asynchronous I/O
            // (theoretically), we need to pass it a callback so
            // that the service layer can alert us to data events
            // when they are available.

            // Build the arguments. Our last argument will always
            // be a callback for our asynchronous API. In this case,
            // the callback will be expecting an API response for a
            // successful call; OR, a null response for a record that
            // could not be found.
            var apiArguments = [function(err, apiResponse ){

                // Check to see if we have a valid API response.
                if (!err){

                    // The API request was successful - announce
                    // the data event.
                    controller.emit( "data", apiResponse, request, response );

                } else {

                    // The API request was not successful - announce
                    // the error event.
                    controller.emit( "error", "404", request, response);

                }

            }];

            // If there is a captured group in the regex pattern
            // that we used above, add it as the first argument to
            // our collection of service-layer invocation arguments.
            if (match.length > 1){

                // Prepend the captured group (an ID) to the list
                // of arguments used to invoke the service layer.
                var obj = querystring.parse(match[1]);
                apiArguments.unshift( obj );

            }

            // Invoke the service layer (remember, the last argument
            // of our invocation array is always the callback for
            // asynchronous I/O).
            me.registerService[ patternKey ].apply(
                me.registerService,
                apiArguments
            );

            // The RESTful URL can only match one pattern.
            // Since we found a match, return out of the request
            // handler as there is nothing more we can do here
            // until the data-callback is triggered.
            return;

        }

    }


    // If we have made it this far, then the incoming request did
    // not match up with any known API signature. As such, we will
    // announce (emit) a server error.
    controller.emit( "error", "500", request, response);

};


// ---------------------------------------------------------- //
// ---------------------------------------------------------- //


// Expose the controller / event emitter. Since we are exposing
// the whole object, rather than just an API interface, we are
// redefining the entire exports value.
module.exports = controller;